package cn.wolfcode.luowowo.service.impl;
import cn.wolfcode.luowowo.domain.User;
import cn.wolfcode.luowowo.exception.LogicException;
import cn.wolfcode.luowowo.repository.UserRepository;
import cn.wolfcode.luowowo.redis.service.IUserRedisService;
import cn.wolfcode.luowowo.service.IUserService;
import cn.wolfcode.luowowo.redis.util.RedisKeys;
import cn.wolfcode.luowowo.util.MyUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;


import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 用户业务接口实现
 */
@Service
public class UserServiceImpl implements IUserService {
    //注入操作mongodb数据库的bean
    @Autowired
    private UserRepository userRepository;
    //注入用户缓存业务服务
    @Autowired
    private IUserRedisService redisService;

    @Override
    public User get(String id) {
        //findById()方法返回的Optional,不是实体类对象,调get方法的话查询不到会报错
        //orElse会做判断,空就返回传入的参数,有值就返回查询到到值
        return userRepository.findById(id).orElse(null);
    }

    //根据手机号查询用户信息
    //如果查询对象为空，则手机号没有注册过返回true 否则返回false
    @Override
    public boolean checkPhone(String phone) {
        return userRepository.findByPhone(phone) == null;
    }

    //发送短信验证码
    @Override
    public void sendVerifyCode(String phone, String url, String appkey) {
        //创建StringBuilder用于操作字符串
        StringBuilder stringBuilder = new StringBuilder();
        //生成验证码,取前4位uuid
        String code = UUID.randomUUID().toString().replace("-", "").substring(0,4);
        //生成短信并发送
        System.out.println(stringBuilder.append("【骆窝窝】注册验证码是").append(code).append(",有效期为").append(RedisKeys.VERIFY_CODE.getTime() / 60).append("分钟"));
        /*String codeUrl = "https://way.jd.com/chuangxin/dxjk?mobile=" + phone +
                "&content=【创信】你的验证码是：" + code +
                ",3分钟内有效！&appkey=a3d986c6d42157e5e5eef148f8f8eee8";
        //利用spring的RestTemplate发生请求
        RestTemplate restTemplate = new RestTemplate();
        //解析url,并填充占位符,发起请求
        String ref = restTemplate.getForObject(url, String.class , phone , stringBuilder.toString() , appkey);
        //判断返回值有没Success表示是否成功
        if (!ref.contains("Success")){
            throw new LogicException("发送失败");
        }
        System.out.println(ref);*/

        //缓存验证码 手机号作为key后缀,验证码作为value，时间为300秒
        redisService.cache(RedisKeys.VERIFY_CODE.join(phone), code, RedisKeys.VERIFY_CODE.getTime());
    }

    /**
     * 注册
     * 前端的验证可以被绕开,为保证程序的健壮性,再次校验
     * @param phone
     * @param nickname
     * @param password
     * @param rpassword
     * @param verifyCode
     */
    @Override
    public void regist(String phone, String nickname, String password, String rpassword, String verifyCode) {
        //调用工具类验证参数内容
        MyUtils.hasLength(phone,"手机号不能为空");
        //验证手机号格式
        MyUtils.isPhonePattern(phone);
        //验证手机号是否注册过
        if (!checkPhone(phone)){
            throw new LogicException("该手机号已经被注册");
        }
        MyUtils.hasLength(nickname,"名称不能为空");
        MyUtils.hasLength(password,"密码不能为空");
        MyUtils.hasLength(rpassword,"确认密码不能为空");
        MyUtils.hasLength(verifyCode,"验证码不能为空");
        //验证两次密码
        MyUtils.isEquals(password,rpassword,"两次密码不一致");
        //查看缓存是否有验证码
        String Rediscode = redisService.check(RedisKeys.VERIFY_CODE.join(phone));
        MyUtils.hasLength(Rediscode,"请先获取验证码");
        MyUtils.isEquals(verifyCode, Rediscode, "验证码错误,或过期");
        //封装数据到用户对象,用于保存到数据库
        User user = new User();
        user.setPhone(phone);
        user.setNickname(nickname);
        //对密码进行加密
        String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
        //设置加密的结果
        user.setPassword(passwordMd5);
        user.setState(User.STATE_NORMAL);
        user.setLevel(0);
        user.setGender(User.GENDER_SECRET);
        user.setHeadImgUrl("");
        user.setEmail("");
        user.setCity("");
        user.setInfo("");
        //保存
        userRepository.save(user);
    }

    /**
     * 登录
     * @param phone
     * @param password
     * @return
     */
    @Override
    public Map<String , String> login(String phone, String password) {
        //调用工具类验证参数内容
        MyUtils.hasLength(phone,"手机号不能为空");
        //验证手机号格式
        MyUtils.isPhonePattern(phone);
        MyUtils.hasLength(password,"密码不能为空");

        //验证账号(手机号)密码
        //查询用户是否存在
        User user = userRepository.findByPhone(phone);
        if (user == null){
             throw new LogicException("账号不存在");
        }
        //如果数据库有这个用户,但是没密码则返回
        MyUtils.hasLength(user.getPassword(),"账号信息异常,联系管理员");
        //对输入的密码进行加密
        String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
        //验证密码
        MyUtils.isEquals(passwordMd5,user.getPassword(),"密码错误");
        //创建唯一的字符串(uuid)作为token,作为缓存用户登陆信息user的key的一部分的
        String token = UUID.randomUUID().toString().replace("-", "");
        //缓存登录信息(密码清除)
        user.setPassword("");
        //缓存用户信息 token作为key后缀,用户信息的JSON字符串作为value，时间为1800秒(30分钟)
        String userJson = JSON.toJSONString(user);
        redisService.cache(RedisKeys.LOGIN_DATE.join(token), userJson, RedisKeys.LOGIN_DATE.getTime());
        //提供获取用户登录信息的凭证token和用户登录信息给页面
        HashMap<String, String> map = new HashMap<>();
        map.put("token",token);
        map.put("user",userJson);
        return map;
    }
    //获取当前登陆用户信息
    @Override
    public User getCurrentUser(String token) {
        //根据token作为key的一部分查询缓存中是否有这个用户信息
        String key = RedisKeys.LOGIN_DATE.join(token);
        String userJson = redisService.check(key);
        //把json信息转换成具体对象
        User user = JSONObject.parseObject(userJson, User.class);
        if (user != null){
            //如果有则重置该用户信息的缓存时间
            redisService.expire(key,RedisKeys.LOGIN_DATE.getTime());
        }
        return user;
    }
}
